#!/bin/bash
###############################################################################
#       脚本名称: test_logger.sh
#       功能描述: 日志模块API接口单元测试
#       作者: 林再来
#       日期: 2025-10-28
#       版本: 1.0
#       功能:
#           1、测试日志API初始化功能
#           2、测试各级别日志记录接口（trace/debug/info/warn/error/fatal）
#           3、测试日志写入核心函数
#           4、测试配置重载功能
#           5、测试上下文管理（trace_id）
#           6、测试资源清理功能
#           7、测试日志系统信息查询
#       依赖(插件/命令):
#           无
###############################################################################

# 获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"

# 加载测试框架
source "$SCRIPT_DIR/../test_framework.sh"

# 临时配置文件目录
TEST_CONFIG_DIR="$PROJECT_ROOT/temp/test_configs"

###############################################################################
# 测试准备和清理
###############################################################################

function setup_test_env() {
    # 创建测试配置目录
    mkdir -p "$TEST_CONFIG_DIR"
    mkdir -p "$PROJECT_ROOT/temp/test_logs"
    
    # 创建测试配置文件
    cat > "$TEST_CONFIG_DIR/test_logger.yaml" <<'EOF'
logger:
  global:
    level: DEBUG
    async: false
    sanitize: false
  
  appenders:
    - name: appender_console
      type: console
      level: DEBUG
      formatter: plain
      enabled: true
      color: false
      target: stdout
    
    - name: appender_test_log
      type: file
      level: DEBUG
      formatter: plain
      enabled: true
      file: temp/test_logs/test.log
      rotation:
        strategy: size
        max_size: 10M
        max_files: 3
EOF
}

function cleanup_test_env() {
    # 清理测试文件
    rm -rf "$TEST_CONFIG_DIR"
    rm -rf "$PROJECT_ROOT/temp/test_logs"
}

###############################################################################
# 测试用例
###############################################################################

#-----------------------------------------------------------------------------
# 测试: 日志系统初始化
#-----------------------------------------------------------------------------
function test_logger_init() {
    setup_test_env
    
    # 清理之前的加载
    unset _LOGGER_LOADED
    
    # 加载日志模块
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    
    # 使用测试配置初始化
    log_init "$TEST_CONFIG_DIR/test_logger.yaml"
    local result=$?
    
    assert_equals "0" "$result" "日志系统初始化应该成功"
    
    # 验证日志系统已加载
    if ! declare -f log_info >/dev/null 2>&1; then
        echo "log_info函数应该存在" >&2
        return 1
    fi
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_trace接口
#-----------------------------------------------------------------------------
function test_log_trace() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录TRACE级别日志（捕获输出）
    local output
    output=$(log_trace "这是TRACE级别日志" 2>&1)
    
    # 验证输出包含消息（取决于配置级别）
    # 由于配置是DEBUG级别，TRACE可能不输出
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_debug接口
#-----------------------------------------------------------------------------
function test_log_debug() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录DEBUG级别日志
    local output
    output=$(log_debug "这是DEBUG级别日志" 2>&1)
    
    # 验证输出包含消息
    assert_contains "$output" "DEBUG" "输出应包含DEBUG级别标识"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_info接口
#-----------------------------------------------------------------------------
function test_log_info() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录INFO级别日志
    local output
    output=$(log_info "这是INFO级别日志" 2>&1)
    
    assert_contains "$output" "INFO" "输出应包含INFO级别标识"
    assert_contains "$output" "这是INFO级别日志" "输出应包含消息内容"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_warn接口
#-----------------------------------------------------------------------------
function test_log_warn() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录WARN级别日志
    local output
    output=$(log_warn "这是WARN级别日志" 2>&1)
    
    assert_contains "$output" "WARN" "输出应包含WARN级别标识"
    assert_contains "$output" "这是WARN级别日志" "输出应包含消息内容"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_error接口
#-----------------------------------------------------------------------------
function test_log_error() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录ERROR级别日志
    local output
    output=$(log_error "这是ERROR级别日志" 2>&1)
    
    assert_contains "$output" "ERROR" "输出应包含ERROR级别标识"
    assert_contains "$output" "这是ERROR级别日志" "输出应包含消息内容"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_fatal接口
#-----------------------------------------------------------------------------
function test_log_fatal() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录FATAL级别日志
    local output
    output=$(log_fatal "这是FATAL级别日志" 2>&1)
    
    assert_contains "$output" "FATAL" "输出应包含FATAL级别标识"
    assert_contains "$output" "这是FATAL级别日志" "输出应包含消息内容"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: log_write核心函数
#-----------------------------------------------------------------------------
function test_log_write() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 使用log_write记录日志
    local output
    output=$(log_write "INFO" "使用log_write记录的日志" 2>&1)
    
    assert_contains "$output" "INFO" "输出应包含INFO级别"
    assert_contains "$output" "log_write" "输出应包含消息"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 带模块名的日志
#-----------------------------------------------------------------------------
function test_log_with_module() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录带模块名的日志
    local output
    output=$(log_info "测试消息" "test_module" 2>&1)
    
    assert_contains "$output" "test_module" "输出应包含模块名"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 带上下文的日志
#-----------------------------------------------------------------------------
function test_log_with_context() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录带上下文的日志
    local output
    output=$(log_info "测试消息" "test_module" "key1=value1" "key2=value2" 2>&1)
    
    assert_contains "$output" "测试消息" "输出应包含消息"
    # 上下文信息的格式取决于具体实现
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 设置和清除追踪ID
#-----------------------------------------------------------------------------
function test_log_trace_id() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 设置追踪ID（使用新API）
    log_context_set_trace_id "test-trace-123"
    
    # 记录日志（应包含trace_id）
    local output
    output=$(log_info "带追踪ID的日志" 2>&1)
    
    # 清除追踪ID（清除所有context）
    log_context_clear
    
    # 再次记录日志（不应包含trace_id）
    local output2
    output2=$(log_info "不带追踪ID的日志" 2>&1)
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 日志系统版本信息
#-----------------------------------------------------------------------------
function test_log_version() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    
    # 获取版本号
    local version
    version=$(log_version)
    
    assert_not_empty "$version" "版本号不应为空"
    assert_matches "$version" "[0-9]+\.[0-9]+\.[0-9]+" "版本号应符合格式"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 日志系统信息输出
#-----------------------------------------------------------------------------
function test_log_info_dump() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 输出系统信息
    local output
    output=$(log_info_dump 2>&1)
    
    assert_contains "$output" "Logger" "应包含Logger字样"
    assert_contains "$output" "版本" "应包含版本信息"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 配置重载
#-----------------------------------------------------------------------------
function test_log_reload() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 重载配置
    log_reload >/dev/null 2>&1
    local result=$?
    
    # 重载可能失败（如果配置无变化或模块未完全支持）
    # 但不应该崩溃
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 日志清理
#-----------------------------------------------------------------------------
function test_log_cleanup() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 执行清理
    log_cleanup
    local result=$?
    
    assert_equals "0" "$result" "清理操作应该成功"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 连续多次日志记录
#-----------------------------------------------------------------------------
function test_log_multiple_writes() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 连续记录多条日志
    for i in {1..10}; do
        log_info "测试日志 $i" >/dev/null 2>&1
    done
    
    # 验证日志文件存在且有内容
    local log_file="$PROJECT_ROOT/temp/test_logs/test.log"
    if [[ -f "$log_file" ]]; then
        local line_count
        line_count=$(wc -l < "$log_file")
        
        # 应该至少有10行
        if [[ $line_count -lt 10 ]]; then
            echo "日志行数不足: $line_count" >&2
            return 1
        fi
    fi
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 不同级别日志混合记录
#-----------------------------------------------------------------------------
function test_log_mixed_levels() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录不同级别的日志
    log_trace "TRACE消息" >/dev/null 2>&1
    log_debug "DEBUG消息" >/dev/null 2>&1
    log_info "INFO消息" >/dev/null 2>&1
    log_warn "WARN消息" >/dev/null 2>&1
    log_error "ERROR消息" >/dev/null 2>&1
    log_fatal "FATAL消息" >/dev/null 2>&1
    
    # 验证日志文件包含不同级别
    local log_file="$PROJECT_ROOT/temp/test_logs/test.log"
    if [[ -f "$log_file" ]]; then
        local content
        content=$(cat "$log_file")
        
        # 根据配置级别，至少应该有DEBUG及以上的日志
        assert_contains "$content" "DEBUG" "应包含DEBUG日志"
        assert_contains "$content" "INFO" "应包含INFO日志"
        assert_contains "$content" "WARN" "应包含WARN日志"
        assert_contains "$content" "ERROR" "应包含ERROR日志"
        assert_contains "$content" "FATAL" "应包含FATAL日志"
    fi
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 特殊字符处理
#-----------------------------------------------------------------------------
function test_log_special_characters() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录包含特殊字符的日志
    local special_msg="特殊字符测试: @#\$%^&*()[]{}|\\;:'\",<>?"
    local output
    output=$(log_info "$special_msg" 2>&1)
    
    # 验证输出不为空
    assert_not_empty "$output" "包含特殊字符的日志应该能输出"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 中文字符支持
#-----------------------------------------------------------------------------
function test_log_chinese_characters() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录包含中文的日志
    local output
    output=$(log_info "中文日志测试：这是一条包含中文的日志消息" 2>&1)
    
    assert_contains "$output" "中文" "应包含中文字符"
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 空消息处理
#-----------------------------------------------------------------------------
function test_log_empty_message() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录空消息
    local output
    output=$(log_info "" 2>&1)
    
    # 应该能处理空消息（不崩溃）
    
    cleanup_test_env
}

#-----------------------------------------------------------------------------
# 测试: 长消息处理
#-----------------------------------------------------------------------------
function test_log_long_message() {
    setup_test_env
    unset _LOGGER_LOADED
    source "$PROJECT_ROOT/scripts/logger/logger.sh"
    log_init "$TEST_CONFIG_DIR/test_logger.yaml" >/dev/null 2>&1
    
    # 记录长消息（超过1000字符）
    local long_msg="$(printf 'X%.0s' {1..1500})"
    local output
    output=$(log_info "$long_msg" 2>&1)
    
    # 应该能处理长消息
    assert_not_empty "$output" "长消息应该能输出"
    
    cleanup_test_env
}

###############################################################################
# 运行所有测试
###############################################################################

function run_all_tests() {
    test_suite_start "日志API接口单元测试"
    
    run_test "日志系统初始化" test_logger_init
    run_test "log_trace接口" test_log_trace
    run_test "log_debug接口" test_log_debug
    run_test "log_info接口" test_log_info
    run_test "log_warn接口" test_log_warn
    run_test "log_error接口" test_log_error
    run_test "log_fatal接口" test_log_fatal
    run_test "log_write核心函数" test_log_write
    run_test "带模块名的日志" test_log_with_module
    run_test "带上下文的日志" test_log_with_context
    run_test "设置和清除追踪ID" test_log_trace_id
    run_test "日志系统版本信息" test_log_version
    run_test "日志系统信息输出" test_log_info_dump
    run_test "配置重载" test_log_reload
    run_test "日志清理" test_log_cleanup
    run_test "连续多次日志记录" test_log_multiple_writes
    run_test "不同级别日志混合" test_log_mixed_levels
    run_test "特殊字符处理" test_log_special_characters
    run_test "中文字符支持" test_log_chinese_characters
    run_test "空消息处理" test_log_empty_message
    run_test "长消息处理" test_log_long_message
    
    test_suite_end
}

# 主函数
function main() {
    run_all_tests
    test_report
    exit_with_test_result
}

# 如果直接执行此脚本，运行所有测试
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main
fi

